package
{
	import com.xcopy.Screen;
	import fl.controls.progressBarClasses.IndeterminateBar;
	import flash.display.MovieClip;
	import flash.events.Event;

	public class Slot25SlotColumn extends Screen
	{
		protected const TIME_SPEED_START:Number       = 0.6; // 從開始加速到達最高點的時間
		protected const TIME_SPEED_HOLD:Number        = 1.6; // 加速到最高點繼續跑動的時間
		protected const TIME_SPEED_EXTRA:Number       = 0.08; // 額外延長時間，一般無 jackpot 時，就是間隔一次
		protected const TIME_SPEED_DUCK:Number        = 0.4; // 從最高速直到停止的時間
		protected const DISTANCE_LENGTH_START:Number  = 4; // 從開始加速到達最高點的距離
		protected const DISTANCE_LENGTH_SECOND:Number = 15; // 跑動時，每秒跑幾格
		protected const DISTANCE_LENGTH_DUCK:Number   = 5; // 從最高速直到停止的距離		
		protected const DISTANCE_LENGTH_HOLD:Number   = int(DISTANCE_LENGTH_SECOND * TIME_SPEED_HOLD);
		public const DISTANCE_LENGTH_JACKPOT:Number   = int(1.8 / TIME_SPEED_EXTRA); // 中 jackpot 的話，要維持幾個  TIME_SPEED_EXTRA
		protected const TIME_STEP:Number              = 0.05; // 跑到下一格的間隔時間
		protected const SPEED_MAX:Number              = 100; // 最高速度
		protected const ITEM_NUM:Number               = 7; // 物品數量
		protected const ITEM_TITLE:Array              = ['大鳥', '浣熊', '毒蛇', '雨蛙', '寶劍', '甲蟲', '土偶', '鳳凰', '鬼鬼', '獎勵', '卷軸'];
		//protected var _debug:Boolean                  = false;
		private const STATE_STOP:Number               = 1; // 靜止
		private const STATE_RUN:Number                = 2; // 加速
		private const STATE_BREAK:Number              = 3; // 煞停
		private const STATE_DUCK:Number               = 4; // 靠岸
		public static const EVENT_STOCK:String        = 'EVENT_STOCK';
		public static const EVENT_STOP:String         = 'EVENT_STOP';
		public static const EVENT_RUN:String          = 'EVENT_RUN';
		public static const EVENT_BREAK:String        = 'EVENT_BREAK';
		public static const EVENT_DUCK:String         = 'EVENT_DUCK';
		protected var _lastTime:Number                = 0; // 最後一次拉霸的時間
		protected var _state:Number                   = STATE_STOP; // 本排目前的狀態
		protected var _items:Vector.<Slot25SlotItem>  = Vector.<Slot25SlotItem>([]); // 本排的子物件
		protected var _height:Number                  = 0; // 一個 ITEM 的高度
		protected var _prepare:Number                 = 0; // 要被抬到上頭 item 編號
		protected var _floatAlready:uint              = 0; // 已經丟了幾個 item 上去 
		protected var _floatTotal:uint                = 0; // 總共會丟幾個 item 上去
		protected var _result:Array                   = []; // 最後應該顯示的三個子物件號碼，由上而下存在 0 1 2 裡
		protected var _extra:Number                   = 0;
		protected var _index:Number                   = 0; // 本列的順位，當事件沸升時要給監聽者使用。
		public var jackpots:Number                    = 0;
		private var _machine:Slot25Machine;
		private var flagFirst:Number;

		public function get machine():Slot25Machine
		{
			return _machine;
		}

		public function get debug():Slot25Debugger
		{
			return machine.debug;
		}

		public function Slot25SlotColumn(r:* = null)
		{
			super(r);
			_machine = r as Slot25Machine;
		}

		// 初始化物件
		override public function set clip(mc:MovieClip):void
		{
			super.clip = mc;
			var i:Number = 0;
			var mv:MovieClip;
			for (i = 0; i < ITEM_NUM; i++)
			{
				mv = clip.getChildByName('oSlot' + (i + 1)) as MovieClip;
				_items[i] = new Slot25SlotItem(this);
				_items[i].clip = mv;
			}
			_height = _items[0].height;
			_prepare = 0;
			_floatAlready = 0;
			flagFirst = NaN;
			_state = STATE_STOP; // 直接指定，不要觸發事件
			initColumn();
		}

		// 初始化本列（物件重新亂數排過，位置由上而下是 43210，其中 321 顯示於中間）
		public function initColumn():void
		{
			var i:Number = 0;
			for (i = 0; i < ITEM_NUM; i++)
			{
				_items[i].icon = int(Math.random() * 8);
				_items[i].y = (4 - i) * _height;
			}
			clip.y = 0;
			_prepare = 0;
			_floatAlready = 0;
			_floatTotal = 0;
			flagFirst = NaN;
		}

		public function resetColumn():void
		{
			var temp:Array  = [];
			var flag:Number = 0;
			var i:Number    = 0;
			if (index == 0)
			{
				debug.print('_prepare = ' + _prepare);
			}
			for (i = 2; i < 5; i++)
			{
				flag = (flagFirst + (i - 2)) % ITEM_NUM;
				//flag = (_prepare + i) % ITEM_NUM;
				temp[i - 2] = _items[flag].icon;
				if (index == 0)
				{
					debug.print('temp[' + (i - 2) + '] = _items[' + flag + ']');
				}
			}
			for (i = 0; i < ITEM_NUM; i++)
			{
				if (i >= 2 && i <= 4)
				{
					_items[i].icon = temp[i - 2];
					if (index == 0)
					{
						debug.print('_items[' + i + '] = temp[' + (i - 2) + ']');
					}
				}
				else
				{
					_items[i].icon = int(Math.random() * 8);
				}
				_items[i].y = (4 - i) * _height;
			}
			clip.y = 0;
			_prepare = 0;
			_floatAlready = 0;
			_floatTotal = 0;
			flagFirst = NaN;
			var s:String = 'column: ' + index + '\n';
			for (i = 0; i < ITEM_NUM; i++)
			{
				s = s + '[ ' + i + ' : ' + _items[i].y + ' ~ ' + _items[i].icon + ' ] ';
			}
			this.debug.print(s);
		}

		public function get ducked():Boolean
		{
			return (state == STATE_STOP);
		}

		/*public function get canBreak():Boolean
		{
			return (state == STATE_RUN || state == STATE_STOP);
		}*/
		public function set index(n:Number):void
		{
			_index = n;
			//_debug = (index == 0);
		}

		public function get index():Number
		{
			return _index;
		}

		public function set state(n:Number):void
		{
			_state = n;
			switch (_state)
			{
				case this.STATE_STOP:
				{
					dispatchEvent(new Event(EVENT_STOP));
					break;
				}
				case this.STATE_RUN:
				{
					dispatchEvent(new Event(EVENT_RUN));
					break;
				}
				case this.STATE_BREAK:
				{
					dispatchEvent(new Event(EVENT_BREAK));
					break;
				}
				case this.STATE_DUCK:
				{
					dispatchEvent(new Event(EVENT_DUCK));
					break;
				}
				default:
					break;
			}
		}

		public function get state():Number
		{
			return _state;
		}

		// 停止該格動畫
		public function normal(index:Number):void
		{
			_items[index].normal();
		}

		// 播放該格動畫
		public function play(index:Number):void
		{
			_items[5 - index].play();
		}

		/*public function debug(s:String):void
		{
			if (!_debug)
			{
				return;
			}
		}*/
		// 開跑（並傳入結果）
		public function startFull(item1:Number, item2:Number, item3:Number, extra:Number):void
		{
			var dt:Date = new Date();
			_result[2] = item1;
			_result[1] = item2;
			_result[0] = item3;
			jackpots = (item1 == 9 ? 1 : 0) + (item2 == 9 ? 1 : 0) + (item3 == 9 ? 1 : 0);
			_extra = extra;
			_lastTime = dt.getTime();
			state = STATE_RUN;
			// 開始！
			//clip.y = 0;
			// 加速到極速後，自動呼叫續跑函數，而在過程中要持續 check 是否上拋
			/*
			for (var i:Number = 0; i < ITEM_NUM; i++)
			{
				_items[i].setBlur(3);
			}
			*/
			addTween(clip, {y: _height * DISTANCE_LENGTH_START, time: TIME_SPEED_START, transition: 'easeInSine', onComplete: continueFull,
					onUpdate: checkFull});
		}

		// 持平
		public function continueFull():void
		{
			// 在起跑之外，比如已經踩煞車或煞停中，就不要再持續跑了
			if (state != STATE_RUN)
			{
				return;
			}
			//trace('極速');
			addCaller(this, {time: TIME_SPEED_HOLD + _extra * TIME_SPEED_EXTRA, count: 1, onUpdate: breakFull, onUpdateParams: [_lastTime]}); // 自動煞車
			addTween(clip, {y: clip.y + _height * DISTANCE_LENGTH_HOLD * 4, time: TIME_SPEED_HOLD * 5, transition: 'linear', onUpdate: checkFull}); // 設定五倍距離讓他跑不完直到煞車
		}

		public function checkFull():void
		{
			if (clip.y >= (_floatAlready + 1) * _height)
			{
				var value:Number = clip.y - (_floatAlready + 1) * _height;
				var time:int     = Math.ceil(value / _height);
				var rand:int;
				/** 判斷目前clip已超出的高度是單格高的幾倍，則需要丟幾格上去 */
				if (time == 0)
				{
					time++;
				}
				for (var i:int = 0; i < time; i++)
				{
					var valid:Boolean;
					do
					{
						valid = false;
						rand = int(Math.random() * 11);
						if (index % 2 != 0 && rand == 8)
						{
							//	只有 1 , 3 , 5 輪會出 wild
							valid = true;
						}
						if ((index == 0 || index == 4) && rand == 9)
						{
							//	只有 2 , 3 , 4 輪會出 jackpot
							valid = true;
						}
						valid = !valid;
					} while (!valid);
					rand = int(Math.random() * 11);
					_items[_prepare].y -= _height * ITEM_NUM;
					switch (_state)
					{
						case STATE_RUN:
						{
							_items[_prepare].icon = rand;
							break;
						}
						case STATE_DUCK:
						{
							var temp:uint = _floatTotal - _floatAlready;
							if (temp >= (DISTANCE_LENGTH_DUCK - 2) && temp <= DISTANCE_LENGTH_DUCK)
							{
								if (isNaN(flagFirst))
								{
									flagFirst = _prepare;
								}
								_items[_prepare].icon = _result[DISTANCE_LENGTH_DUCK - temp];
								if (index == 0)
								{
									debug.print('_items[' + _prepare + '] = _result[' + (DISTANCE_LENGTH_DUCK - temp) + ']');
								}
							}
							else
							{
								_items[_prepare].icon = rand;
							}
							break;
						}
					}
					_floatAlready++;
					_prepare = (_prepare + 1) % ITEM_NUM;
				}
				// 若狀態為煞車，則開始 duck 設定
				if (state == STATE_BREAK)
				{
					duckFull();
				}
			}
		}

		// 煞車，將會由外面按下停止鈕，或是跑動時間到而自動呼叫，呼叫後改變狀態為煞車，等待 doFull 自動判斷煞停
		public function breakFull(time:Number = -1):void
		{
			if (time == -1)
			{
				time = _lastTime;
			}
			if (state == STATE_RUN && time == _lastTime)
			{
				//trace('拉煞車');
				state = STATE_BREAK;
			}
		}

		/**	靠岸：有可能是正常的煞停或手動煞停 */
		public function duckFull():void
		{
			removeTweens(clip); // 不管他現在在哪裡，先停掉原來的動畫，然後加上停駐動畫			
			state = STATE_DUCK;
			_floatTotal = _floatAlready + DISTANCE_LENGTH_DUCK;
			dispatchEvent(new Event(EVENT_STOCK));
			addTween(clip, {y: _height * _floatTotal, time: TIME_SPEED_DUCK, transition: 'easeOutBack', onComplete: clearFull, onUpdate: checkFull});
		}

		// 清除
		public function clearFull():void
		{
			state = STATE_STOP;
			resetColumn();
		}
	}
}
